package com.teamone.etl.datasource.pool;

import com.teamone.etl.datasource.entity.DataSource;
import java.sql.*;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.StringUtils;

import static com.teamone.etl.constant.EtlConstant.JdbcConstant.*;
import static com.teamone.etl.constant.EtlConstant.TypeConstant.*;

/**
 *@author WangZhuoRan
 * @Description JDBC连接池工具类
 * @Author WangZhuoRan
 * @Date 2021-01-07 19:10
 */
public class JdbcConnector {

    public static final Map<Integer, Connection> JDBC_POOL_MAP = new ConcurrentHashMap<>(64);

    private static Connection createConnection (DataSource info) {
        Connection conn = null;
        try {
            StringBuffer sb;
            if (info.getTypeId() == MYSQL) {
                Class.forName(MYSQL_DRIVER);
                sb=new StringBuffer(MYSQL_PRE);
                sb.append(info.getHost()).append(":").append(info.getPort());
                if (! StringUtils.isEmpty(info.getExtraConfigParam())) {
                    sb.append(info.getExtraConfigParam());
                }
            } else if (info.getTypeId() == ORACLE) {
                Class.forName(ORACLE_DRIVER);
                sb=new StringBuffer(ORACLE_PRE);
                sb.append(info.getHost()).append(":").append(info.getPort());
            } else if (info.getTypeId() == SQL_SERVER) {
                Class.forName(SQLSERVER_DRIVER);
                sb=new StringBuffer(SQLSERVER_PRE);
                sb.append(info.getHost()).append(":").append(info.getPort());
            } else {
                return null;
            }
            String url = sb.toString();
            conn = DriverManager.getConnection(url, info.getUsername(),info.getPassword());
        } catch (SQLException | ClassNotFoundException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    /**
     * @Description 初始化连接池
     * @Author WangZhuoRan
     * @Date 2021-01-07 10:21
     * @param info 所有数据源信息
     */
    public static void initJdbcPoopMap (List<DataSource> info){
        info.forEach(JdbcConnector::put);
    }

    /**
     * @Description 向连接池 添加新连接/更新
     * @Author WangZhuoRan
     * @Date 2021-01-07 10:22
     * @param dataSource 数据源信息
     */
    public static Boolean put(DataSource dataSource){
        Connection connection = createConnection(dataSource);
        if(connection!=null){
            Boolean connected = isConnected(connection, dataSource);
            if(connected){
                JDBC_POOL_MAP.put(dataSource.getId(), connection);
                return true;
            }
        }
        return false;
    }

    /**
     * @Description 判断是否连接
     * @Author WangZhuoRan
     * @Date 2021-01-12 20:42
     * @param connection 链接源
     * @param dataSource 数据源信息
     * @return java.lang.Boolean
     */
    private static Boolean isConnected(Connection connection,DataSource dataSource){
        boolean flag=false;
        try {
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(MYSQL_SQLSERVER_TEST_SQL);
            if (dataSource.getTypeId()==ORACLE){
                resultSet = statement.executeQuery(ORACLE_TEST_SQL);
            }else if(dataSource.getTypeId()== SQL_SERVER){
                resultSet = statement.executeQuery(MYSQL_SQLSERVER_TEST_SQL);
            }
            while (resultSet.next()){
                String version = resultSet.getString("version");
                if(version!=null){
                    flag=true;
                }
            }
            if(dataSource.getId()==null){
                connection.close();
            }
            statement.close();
            resultSet.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return flag;
    }

    public static Boolean isConnected(DataSource dataSource){
        Connection connection;
        if(dataSource!=null){
            if(dataSource.getId()!=null){
                connection = JDBC_POOL_MAP.get(dataSource.getId());
            }else{
                connection = createConnection(dataSource);
            }
            if(connection!=null){
                return isConnected(connection, dataSource);
            }
        }
        return false;
    }

    /**
     * @Description 关闭所有连接
     * @Author WangZhuoRan
     * @Date 2021-01-07 09:19
     */
    public static void closeAll(){
        JDBC_POOL_MAP.forEach((id, connection) -> {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        });
    }

    /**
     * @Description 判断是否在工作
     * @Author WangZhuoRan
     * @Date 2021-01-07 10:21
     * @param connection 判断的数据源连接对象
     * @return java.lang.Boolean
     */
    public static Boolean isNotWorked (Connection connection){
        try {
            String query = connection.getClientInfo("isworking");
            if (query==null || IS_WORKING.equals(query)){
                return true;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return false;
    }

    /**
     * @Description 判断是否在工作
     * @Author WangZhuoRan
     * @Date 2021-01-07 10:21
     * @param dataSourceId 判断的数据源连接对象的主键ID
     * @return java.lang.Boolean
     */
    public static Boolean isNotWorked (Integer dataSourceId){
        return isNotWorked(JDBC_POOL_MAP.get(dataSourceId));
    }

}
